model carrefour
/*
 *  tinh tong thoi gian cho cua cac xe 
 * 
 */
global {
	//global shape file
	file shape_file_lane <- file('../includes/crossroads/lane1.shp');
	file shape_file_bounds <- file('../includes/crossroads/bounds.shp');
	file shape_file_terrain <- file('../includes/crossroads/terrain1.shp');
	file shape_file_starting_point <- file('../includes/crossroads/starting_point.shp');
	file shape_file_ending_point <- file('../includes/crossroads/ending_point.shp');
	file shape_file_waiting_area <- file('../includes/crossroads/waiting_area.shp');
	file shape_file_traffic_light <- file('../includes/crossroads/traffic_light3.shp');
	//parametes environment
	float level_civilization min:0.0 max:1.0 <- 1.0;
	float rnd_factor_appear min:0.0 max:1.0 <- 0.1;
	int rnd_nb_appear min:0 max:10 <- 10;
	int time_to_appear <- 5;
	//parametes traffic light
	const periode_time_light type:int <- 200;
	int time_start_1 <- 0;
	int time_start_2 <- periode_time_light;
	int time_start_3 <- 0;
	int time_start_4 <- periode_time_light;

	int time_green_1 <- int(periode_time_light * 24/25);
	int time_green_2 <- int(periode_time_light * 24/25);
	int time_green_3 <- int(periode_time_light * 24/25);
	int time_green_4 <- int(periode_time_light * 24/25);
	
	int time_yellow_default <- int(periode_time_light / 25);
	
	int time_red_2 <- periode_time_light;
	int time_red_3 <- periode_time_light;
	int time_red_4 <- periode_time_light;
	int time_red_1 <- periode_time_light;
	//others
	int time_tobe_furius <- 300;
	int repulsion_strength min: 1 <- 10 ;
	int nb_vehicule_startup <- 20;
	float min_speed <- 2.0;
	float max_speed <- 6.0;
	int min_size_of_vehicle <- 5;
	int max_size_of_vehicle <- 10;
	graph the_graph;
	int range_of_vehicules min:1 <- 10;
	
	list list_time_start <- [time_start_1, time_start_2, time_start_3, time_start_4];
	list list_time_green <- [time_green_1, time_green_2, time_green_3, time_green_4];
	list list_time_yellow <-[time_yellow_default,	time_yellow_default,	time_yellow_default,	time_yellow_default];
	list list_time_red <-   [time_red_1,   time_red_2,   time_red_3,   time_red_4];
	
	list list_wa <- waiting_area as list;
	init {
		create waiting_area		from: shape_file_waiting_area;
		create lane 			from: shape_file_lane;
		set the_graph <- as_edge_graph(list(lane));
		create terrain 			from: shape_file_terrain;
		create starting_point 	from: shape_file_starting_point;
		create ending_point 	from: shape_file_ending_point;
		create traffic_light 	from: shape_file_traffic_light
				with:[id_light::read('id')]{
					set time_start <- list_time_start at id_light ;
					set time_green <- list_time_green at id_light ;
					set time_red   <- list_time_red   at id_light ;
					set time_yellow <- list_time_yellow at id_light ;
					set total_time <- time_red + time_green + time_yellow;
				}
		
		create vehicle number: nb_vehicule_startup{
			set location <- any_location_in( one_of(starting_point));
			set speed <- min_speed + rnd(max_speed - min_speed);
			set the_starting_point <- one_of (starting_point);
			set the_ending_point <- one_of (ending_point);
			set the_target <- any_location_in(the_ending_point);
			set is_waiting_light <- false;
		}
	}
	
//	co the fai xem lai ham nay
	reflex create_vehicles when : every(time_to_appear){
		create vehicle number: rnd_nb_appear{
			set location <- any_location_in( one_of(starting_point));
			set speed <- min_speed + rnd(max_speed - min_speed);
			set speed_backup <- speed;
			set the_starting_point <- one_of (starting_point);
			set the_ending_point <- one_of (ending_point);
			set the_target <- any_location_in(the_ending_point);
			set is_waiting_light <- false;
		}
	}
	
}
entities {
	species traffic_light control:fsm{
		int id_light <- 0;
		int time_start <- list_time_start at id_light;
		int time_red <- list_time_red at id_light;
		int time_green <- list_time_green at id_light;
		int time_yellow <-list_time_yellow at id_light;
		int total_time <- time_red + time_green + time_yellow;
		int cycle_time update:int((time - time_start >= 0)?
			(time - time_start) mod (total_time)
			:(total_time - (time_start - time)));
			
		int count_down update:(cycle_time < time_green)? time_green-cycle_time:total_time-cycle_time; 
		rgb color <- rgb('red');
		
		state startup initial:true{
//			set color <- rgb('red');
			transition to: in_red when: cycle_time >= time_green + time_yellow and cycle_time < total_time;
			transition to: in_green when: cycle_time >= 0 and cycle_time < time_green;
			transition to: in_yellow when: cycle_time >= time_green and cycle_time < time_green + time_yellow;
		}
		
		state in_green {
			set color <- rgb('green');
			transition to: in_yellow when: cycle_time = time_green;
		}
		
		state in_yellow {
			set color <- rgb('yellow');
			transition to: in_red when: cycle_time = time_green + time_yellow;
		}
		
		state in_red {
			set color <- rgb('red');
			transition to: in_green when: cycle_time =0;
		}
		
		aspect base {
			draw geometry: shape color: color ;
			draw text: string(count_down) at: location + {-7,3} color: rgb('black') size: 10.8 ;
			
		}
	}
	
	species waiting_area {
		rgb color <- rgb('gray');
		aspect base {
			draw geometry: shape color: color ;
		}
	}
	
	species lane  {
		rgb color <- rgb('white') ;
		aspect base {
			draw geometry: shape color: color ;
		}
	}
	
	species terrain {
		string type;
		rgb color <- rgb([0,191,255]);
		aspect base {
			draw geometry: shape color: color;
			
		}
	}
	
	species starting_point {
		rgb color <- rgb('white');
		aspect base {
			draw geometry: shape color: color;
		}
	}
	
	species ending_point {
		rgb color <- rgb('white');
		aspect base {
			draw geometry: shape color: color;
		}
	}
	
	species vehicle skills:[moving] {
//		variable primitive
		int size min:5 <- rnd(max_size_of_vehicle - min_size_of_vehicle) + min_size_of_vehicle;
		
		const range type: float <- float(range_of_vehicules);
		float speed <- rnd(max_speed - min_speed)+ min_speed;
		float speed_backup <- speed;
//		variable topo
		starting_point the_starting_point <- nil;
		ending_point the_ending_point <- nil;
		point the_target <- nil;
//		variable status
		bool in_waiting_area  update: self.shape intersects one_of(list(waiting_area));
		bool is_waiting_light <- false;
		bool is_polite <- false;		
		int waiting_time init:0 update:is_waiting_light?(waiting_time + 1):(waiting_time) ;
		rgb color update:is_waiting_light?rgb('red'):rgb('green');
		
		reflex goto_target when: !is_waiting_light{
			do action: goto_target; 
		}
		
		action goto_target {
//			set speed <- rnd(max_speed);
			do goto target: the_target on: the_graph;
			switch the_target {
				match location {do action:die;}
			}
		}
		
//		when:!is_polite
		reflex elbow {
			let close type: vehicle <- one_of (((self neighbours_at range ) of_species vehicle) sort_by (self distance_to each));
			if (close != nil){
				set heading <- (self towards close ) - 180 ;
				let dist <- self distance_to close;
				do move speed: max([dist/ repulsion_strength,0]) heading: heading ;
			}
		}
		
		reflex imitate_wait when:!is_waiting_light and flip(level_civilization){
			let close type: vehicle <- one_of (((self neighbours_at range ) of_species vehicle) sort_by (self distance_to each));
			if close != nil and close.is_waiting_light{
				set is_waiting_light <- true;
			}
		}
		
//		reflex keep_distance when:is_polite{
//			let close type: vehicle <- one_of (((self neighbours_at range ) of_species vehicle) sort_by (self distance_to each));
//			if (close !=nil){
//				set speed <- 0;
//			} else{
//				set speed <- speed_backup;
//			}
//		}
		
		reflex focus_on_light when: in_waiting_area and !is_waiting_light and flip(level_civilization){
			let nearby_light type:traffic_light value:first((list(traffic_light) sort_by( self distance_to each)));		
				if nearby_light.state = 'in_red' or nearby_light.state = 'in_yellow'{
					set speed_backup <- speed;
					set speed <- 0;
					set is_waiting_light <- true;
				}
		}
		
		reflex check_to_go when: is_waiting_light{
			let nearby_light type:traffic_light value:first((list(traffic_light) sort_by( self distance_to each)));		
				if nearby_light.state = 'in_green'{
					set speed <- speed_backup;
					set is_waiting_light <- false;
				}
		}
		
		reflex become_furius when: is_waiting_light{
			let deltaColor <- int(255*waiting_time/time_tobe_furius);
			set color <- rgb([
                        (color.red + deltaColor > 255) ? 255 : (color.red + deltaColor),
                        (color.green - deltaColor < 0) ? 0 : (color.green - deltaColor),
                        0
                ]);
		}
		reflex check_if_in_wa {
			loop wa over: list_wa{
				if self.shape overlaps wa.shape{
					set in_waiting_area <- true;
				}
			}	
		}
		
		aspect base {
			draw shape: circle color: color size:size;
			draw text: string(waiting_time) at: location + {-3,1.5} color: rgb('black') size: 5.8 ;
		}
	}
}

environment bounds: shape_file_bounds ;
	
experiment crossroads type: gui {
	
//	parameter 'Shapefile for the lignes:' var: shape_file_lane category: 'GIS' ;
//	parameter 'Shapefile for the terrains:' var: shape_file_terrain category: 'GIS' ;
//	parameter 'Shapefile for the starting_points:' var: shape_file_starting_point category: 'GIS';
//	parameter 'Shapefile for the ending_points:' var: shape_file_ending_point category: 'GIS';
//	parameter 'Shapefile for the feux:' var: shape_file_traffic_light category: 'GIS';
//	parameter 'Shapefile for the feux areas:' var: shape_file_waiting_area category: 'GIS';
	
	parameter 'level of civilization' var:level_civilization category: 'global';
	parameter 'the probabiliste factor appear the vehicles' var:rnd_factor_appear category:'global';
	parameter 'the number of vehicles to appea' var:rnd_nb_appear category:'global';
	parameter 'number of vehicles startup ' var:nb_vehicule_startup category:'global';
	parameter 'time_to_appear vehicle' var:time_to_appear category:'global';
//	parametes traffic light
	parameter 'the interval of traffic light' var:periode_time_light category:'traffic_light';
//	parameters vehicle
	parameter 'the time to make the driver become furius' var:time_tobe_furius category:'vehicle';
	output {
		display crossroads_display refresh_every: 1 {
			species waiting_area aspect:base;
			species terrain 	aspect:base;
			species lane 		aspect:base;
			species starting_point aspect: base;
			species ending_point aspect: base;
			species vehicle 	aspect: base;
			species traffic_light aspect:base;
		}
		display total_block refresh_every:5{
			chart total_block
				type: 'series'{
					data total_block
						value: list(vehicle) count(each.is_waiting_light) / 10
						color:rgb('black')
						style:line;
					data is_waiting_light
						value:list(vehicle) count(each.is_waiting_light)
						color:rgb('red')
						style:line;
					data is_circuling
						value:list(vehicle) count(!each.is_waiting_light)
						color:rgb('green')
						style:line;
			}
		}
		display total_waiting_time refresh_every:5{
			chart total_waiting_time
				type: 'series'{
					data total_waiting_time
						value: sum(list(vehicle) collect each.waiting_time)
						color:rgb('red')
						style:line;
			}
		}
		
	}
}